package Java8;

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamTest {

    public static void main(String[] args) {
        streamTest();
        System.out.println("============================");
        listStreamTest();
        System.out.println("============================");
        listByStream();
    }


    /**
     * Stream的基本操作
     */
    public static void streamTest(){
        String[] arr = new String[]{"b","ab","abc","abcd","abcde"};
        System.out.print("原数组：");
        for(String ar : arr){
            System.out.print(ar+" ");
        }

        System.out.println("\n最大最小值：");
        //最大最小值
        Stream.of(arr).max(Comparator.comparing(String::length)).ifPresent(System.out::println);
        Stream.of(arr).min(Comparator.comparing(String::length)).ifPresent(System.out::println);
        //计算数量
        long count = Stream.of(arr).count();
        System.out.println("计算数量：" + count);
        //查找第一个；长度大于3的字符串，找不到返回 NONE
        String str = Stream.of(arr).filter(x -> x.length()>3).findFirst().orElse("NONE");
        //parallel并行流
//        String str = Stream.of(arr).parallel().filter(x -> x.length()>3).findFirst().orElse("NONE");
        System.out.println("查找第一个：" + str);
        //是否含有匹配元素
        Boolean aBoolean = Stream.of(arr).anyMatch(x -> x.startsWith("a"));
        System.out.println("是否含有匹配元素：" + aBoolean);
    }

    /**
     * List Stream的基本操作
     */
    public static void listStreamTest(){
        List<String> strings = Arrays.asList("abc", "", "bc", "efg", "abcd","", "jkl");
        //filter：过滤掉不符合的数据
        List<String> filtered = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.toList());
        //count：统计数据数量
        long countEmpty = strings.stream().filter(string -> string.isEmpty()).count();
        //Collectors 类实现归约操作；将流转换成集合和聚合元素，返回列表或字符串
        String mergedString = strings.stream().filter(string -> !string.isEmpty()).collect(Collectors.joining(", "));
        System.out.println("原列表: " + strings);
        System.out.println("筛选列表: " + filtered);
        System.out.println("统计列表空字符串数量: " + countEmpty);
        System.out.println("合并字符串: " + mergedString);

        System.out.println("----------------------------");

        List<Integer> numbers = Arrays.asList(3, 2, 2, 3, 7, 3, 5);
        // map 方法用于映射每个元素到对应的结果；distinct：去重复数据；获取对应的平方数
        List<Integer> squaresList = numbers.stream().map(i -> i*i).distinct().collect(Collectors.toList());
        System.out.println("原列表: " + numbers);
        System.out.println("平方数去重: " + squaresList);

        System.out.println("----------------------------");

        //int、double、long等基本数据类型的统计
        IntSummaryStatistics stats = numbers.stream().mapToInt(x -> x).summaryStatistics();
        System.out.println("列表中最大的数 : " + stats.getMax());
        System.out.println("列表中最小的数 : " + stats.getMin());
        System.out.println("所有数之和 : " + stats.getSum());
        System.out.println("平均数 : " + stats.getAverage());

        // 并行处理，只需将Stream换成parallelStream

        System.out.println("----------------------------");

        Random random = new Random();
        System.out.println("随机生成的数据：");
        //limit：只取前x条数据；'forEach' 方法迭代流中的每个数据
        random.ints().limit(5).forEach(System.out::println);
        System.out.println("排序后的数据：");
        //sorted 方法用于对流进行排序
        random.ints().limit(5).sorted().forEach(System.out::println);

        System.out.println("----------------------------");

        //生成一亿条0-100之间的记录
        List<Integer> listInteger = Stream.generate(() -> random.nextInt(100)).limit(100000000).collect(Collectors.toList());
        long begin1 = System.currentTimeMillis();
        listInteger.stream().filter(x -> (x > 10)).filter(x -> x<80).count();
        long end1 = System.currentTimeMillis();
        System.out.println(end1-begin1);
        //将普通顺序执行的流转变为并行流，只需要调用顺序流的parallel() 方法即可
        listInteger.stream().parallel().filter(x -> (x > 10)).filter(x -> x<80).count();
        long end2 = System.currentTimeMillis();
        System.out.println(end2-end1);

        long begin1_ = System.currentTimeMillis();
        listInteger.stream().filter(x -> (x > 10)).filter(x -> x<80).distinct().sorted().count();
        long end1_ = System.currentTimeMillis();
        System.out.println(end1-begin1);
        listInteger.stream().parallel().filter(x -> (x > 10)).filter(x -> x<80).distinct().sorted().count();
        long end2_ = System.currentTimeMillis();
        System.out.println(end2_-end1_);
    }

    /**
     * list.stream()：集合list利用stream方法,获取一个流, 方便进行数据的聚合处理等
     * 例子：随机产生100个分数, 并使用流处理.,计算出最高分,最低分和平均
     */
    public static void listByStream(){
        ArrayList<Integer> list = new ArrayList<>();
        Random rd = new Random();
        for (int i = 0; i < 100; i++) {
            list.add(rd.nextInt(101));// 随机产生一个[0,100]的数字
        }
        System.out.println(list);
        // 流处理, 进行数据处理
        DoubleSummaryStatistics ds = list.stream().collect(Collectors.summarizingDouble(e -> e));
        System.out.println("平均分"+ds.getAverage());
        System.out.println("最高分"+ds.getMax());
        System.out.println("最低分"+ds.getMin());
    }

}
